package gq.example.config;

import com.alibaba.fastjson2.JSON;
import gq.example.context.BaseContext;
import gq.example.dto.LoginSuccessDto;
import gq.example.entity.Permission;
import gq.example.entity.Users;
import gq.example.filter.ResourceCleanupFilter;
import gq.example.mapper.UsersAndRoleMapper;
import gq.example.mapper.UsersMapper;
import gq.example.utils.JwtUtil;
import gq.example.result.Result;
import gq.example.service.IUsersService;
import jakarta.servlet.http.HttpServletRequest;
import org.jose4j.jwt.JwtClaims;
import org.jose4j.jwt.consumer.InvalidJwtException;
import org.jose4j.lang.JoseException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.security.authorization.AuthorizationDecision;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.access.intercept.AuthorizationFilter;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.web.cors.CorsConfiguration;

import java.util.ArrayList;
import java.util.List;


@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Autowired
    private UsersMapper usersMapper;

    @Autowired
    private IUsersService usersService;

    @Autowired
    private UsersAndRoleMapper usersAndRoleMapper;

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {


        http.formLogin(form -> {

            form.loginProcessingUrl("/user/login") // 表单提交路径
                    .usernameParameter("username") // 表单中用户名项
                    .passwordParameter("password") // 表单中密码项
                    .successHandler(authenticationSuccessHandler())
                    .failureHandler(authenticationFailureHandler())
                    .permitAll();
        });

        http.authorizeHttpRequests(resp -> {
            resp.requestMatchers("/user/login","/user/register","/doc.html","/v3/api-docs/**", "/swagger-ui.html", "/webjars/**", "/swagger-resources/**","/favicon.ico").permitAll(); // 无需认证
            resp.requestMatchers("**.css", "**.js", "/img/**").permitAll(); // 无需认证
            resp.requestMatchers("/file/upload","/feedback/page","/user/findUser","/user/forgetPassword","/feedback/count","/user/updateUser").permitAll();

            resp.anyRequest().access((authentication, requestContext) -> {
                HttpServletRequest request = requestContext.getRequest();
                String requestUri = request.getRequestURI();
                System.out.println("哥们你咋来了，你的路径是这个：" + requestUri);

                try {
                    String token = extractToken(request);
                    System.out.println("token:" + token);
                    JwtClaims claims = JwtUtil.parseToken(token);
                    List<Permission> permissions = usersMapper.findPermissionByUsername(
                            (String) claims.getClaimValue("username")
                    );
                    BaseContext.setCurrentId((long) claims.getClaimValue("uid"));

                    // 检查用户是否有访问当前URI的权限
                    boolean hasPermission = checkPermission(permissions, requestUri);

                    return new AuthorizationDecision(hasPermission);
                } catch (InvalidJwtException e) {
                    throw new RuntimeException(e);
                } catch (JoseException e) {
                    throw new RuntimeException(e);
                }
            });
        });

        //会话配置
        http.sessionManagement(session -> {
            session.maximumSessions(1);//最大并发会话数
        });

        http.csrf(csrf -> {
                    csrf.disable();
                })
                .cors(cors -> cors.configurationSource(request -> {
                    CorsConfiguration corsConfiguration = new CorsConfiguration();
                    corsConfiguration.addAllowedOrigin("*");
                    corsConfiguration.addAllowedHeader("*");
                    corsConfiguration.addAllowedMethod("*");
                    return corsConfiguration;
                }));
        http.addFilterAfter(new ResourceCleanupFilter(), AuthorizationFilter.class);

        return http.build();
    }

    @Bean
    //密码编译器
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public AuthenticationSuccessHandler authenticationSuccessHandler() {
        return (request, response, authentication) -> {
            try {
                // 1. 从认证信息中获取用户详情
                UserDetails userDetails = (UserDetails) authentication.getPrincipal();

                Users user = usersService.findUserByUsername(userDetails.getUsername());

                // 2. 生成JWT令牌
                String token = JwtUtil.sign(user.getUid(), user.getUsername());
                LoginSuccessDto loginSuccessDto = new LoginSuccessDto();
                if(user.getSectorid() != null){
                    loginSuccessDto.setSectorid(user.getSectorid());
                }
                loginSuccessDto.setToken(token);
                loginSuccessDto.setUsername(user.getUsername());
                loginSuccessDto.setUid(user.getUid());
                loginSuccessDto.setRid(usersAndRoleMapper.findRidByUid(user.getUid()));
                // 3. 返回JSON格式的令牌
                response.setContentType("application/json;charset=UTF-8");
                response.getWriter().write(
                        JSON.toJSONString(Result.success("登陆成功", loginSuccessDto))
                );
            } catch (Exception e){
                e.printStackTrace();
            }
        };
    }

    @Bean
    public AuthenticationFailureHandler authenticationFailureHandler() {
        return (request, response, exception) -> {
            response.setStatus(HttpStatus.UNAUTHORIZED.value());
            response.setContentType("application/json;charset=UTF-8");
            response.getWriter().write(
                    JSON.toJSONString(Result.error("登录失败:" + exception.getMessage()))
            );
        };
    }

    private String extractToken(HttpServletRequest request) throws InvalidJwtException, JoseException {
        String header = request.getHeader("Token");
        JwtUtil jwtUtil = new JwtUtil();
        if (header != null && header.startsWith("Bearer ")) {
            return header.substring(7);
        }
        return null;
    }

    private boolean checkPermission(List<Permission> permissions, String requestUri) {

        for (Permission permission : permissions) {
            String permissionUrl = permission.getUrl();

            if (requestUri.equals(permissionUrl)) {
                return true;
            }

            if (permissionUrl.endsWith("/") && requestUri.startsWith(permissionUrl)) {
                return true;
            }
        }
        return false;
    }

}
